{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "from scipy import stats\n",
    "\n",
    "import math"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 0 Load Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "raw_data = pd.read_csv(\"fingerprint_data.csv\",  dtype={'imsi':np.str})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(11094, 72)"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "raw_data.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Index(['user_id', 'idfa', 'imei', 'mac', 'imsi', 'android_id', 'phone_model',\n",
       "       'phone_name', 'networktype', 'version', 'lcd', 'phone_os', 'battery',\n",
       "       'totalmemory', 'availablememory', 'totalsystem', 'availablesystem',\n",
       "       'totalsd', 'availablesd', 'udid', 'basestation', 'rssi', 'mnc', 'mcc',\n",
       "       'cellid', 'lac', 'nearbybasestation', 'displayrom', 'currentwifi',\n",
       "       'simulator', 'product', 'hardware', 'stat', 'sdkversion', 'brightness',\n",
       "       'cpuspeed', 'simstate', 'fingerprint', 'hascellular', 'haswifi',\n",
       "       'hasgps', 'hastelephony', 'hasbluetooth', 'simserial',\n",
       "       'gravitysensorlist', 'grav_x', 'grav_y', 'grav_z', 'simlac',\n",
       "       'simstrength', 'gyroscopesensorlist', 'x', 'y', 'z',\n",
       "       'pressuresensorlist', 'type', 'tags', 'networkoperator', 'manufacturer',\n",
       "       'device', 'currenttime', 'cpuabi', 'cellularip', 'networkcountryiso',\n",
       "       'simcountryiso', 'bluetooth', 'host', 'cpuarchitecture',\n",
       "       'imanufacturer', 'timestamp', 'ethip', 'trueip'],\n",
       "      dtype='object')"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "raw_data.columns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>user_id</th>\n",
       "      <th>idfa</th>\n",
       "      <th>imei</th>\n",
       "      <th>mac</th>\n",
       "      <th>imsi</th>\n",
       "      <th>android_id</th>\n",
       "      <th>phone_model</th>\n",
       "      <th>phone_name</th>\n",
       "      <th>networktype</th>\n",
       "      <th>version</th>\n",
       "      <th>...</th>\n",
       "      <th>cellularip</th>\n",
       "      <th>networkcountryiso</th>\n",
       "      <th>simcountryiso</th>\n",
       "      <th>bluetooth</th>\n",
       "      <th>host</th>\n",
       "      <th>cpuarchitecture</th>\n",
       "      <th>imanufacturer</th>\n",
       "      <th>timestamp</th>\n",
       "      <th>ethip</th>\n",
       "      <th>trueip</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>172f9196f18c352e1f05f201b33b42a9</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0e1acca629252a67655961347b8adc3d</td>\n",
       "      <td>7554648548ef0960bcd5846df31158a1</td>\n",
       "      <td>51e3532c6c7bc2b2e965a82c7cd0e030</td>\n",
       "      <td>afc20369ad52cf971becb7b160b42ed6</td>\n",
       "      <td>OPPO R11</td>\n",
       "      <td>OPPO</td>\n",
       "      <td>4G</td>\n",
       "      <td>6.2.9</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>ffe3323a2ad276fb7bf23368a6630bf0</td>\n",
       "      <td>NaN</td>\n",
       "      <td>9789222e24733cdfcfde4c73b02566ec</td>\n",
       "      <td>84d9d352d7a8f1399ff3bf69ae4f923d</td>\n",
       "      <td>7c0ddefb46fa8e83010df6f7ab822b4d</td>\n",
       "      <td>8812c1eb3cbc8e9639fa05dc99306cba</td>\n",
       "      <td>LLD-AL10</td>\n",
       "      <td>HONOR</td>\n",
       "      <td>4G</td>\n",
       "      <td>6.2.9</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>557a3047db74899ee335d2671c111085</td>\n",
       "      <td>NaN</td>\n",
       "      <td>22fa26b3c10d60e47b0f05cdb927f196</td>\n",
       "      <td>620744a255478602e8907eb8b7cccb14</td>\n",
       "      <td>958c048515b88d377c9e652e9b57d44c</td>\n",
       "      <td>NaN</td>\n",
       "      <td>M2 E</td>\n",
       "      <td>Meizu</td>\n",
       "      <td>WIFI</td>\n",
       "      <td>6.2.9</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>afb043d6eab80de68ee26f7338f70283</td>\n",
       "      <td>NaN</td>\n",
       "      <td>9565b8a927208f09070bff052fb515e6</td>\n",
       "      <td>2f94fc14b3b5ff0594e1e6c04e479220</td>\n",
       "      <td>43f60b5c38e2ad152569e233a5cb88fe</td>\n",
       "      <td>eef0ca1307bf574408a6f04068c66eb3</td>\n",
       "      <td>PRO 6s</td>\n",
       "      <td>Meizu</td>\n",
       "      <td>WIFI</td>\n",
       "      <td>6.2.9</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>249a64571021d07cd1dd63df02ac9374</td>\n",
       "      <td>NaN</td>\n",
       "      <td>cd30c16e91df0b870c963a3475a6bace</td>\n",
       "      <td>fbbe8f9dc741910b6e2b2d739a8254f3</td>\n",
       "      <td>8276231c14b21cf9f8339e53c6482a4a</td>\n",
       "      <td>cfb381ccd7104f5728799d0678838378</td>\n",
       "      <td>vivo X7</td>\n",
       "      <td>vivo</td>\n",
       "      <td>4G</td>\n",
       "      <td>6.2.8</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 72 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                            user_id  idfa                              imei  \\\n",
       "0  172f9196f18c352e1f05f201b33b42a9   NaN  0e1acca629252a67655961347b8adc3d   \n",
       "1  ffe3323a2ad276fb7bf23368a6630bf0   NaN  9789222e24733cdfcfde4c73b02566ec   \n",
       "2  557a3047db74899ee335d2671c111085   NaN  22fa26b3c10d60e47b0f05cdb927f196   \n",
       "3  afb043d6eab80de68ee26f7338f70283   NaN  9565b8a927208f09070bff052fb515e6   \n",
       "4  249a64571021d07cd1dd63df02ac9374   NaN  cd30c16e91df0b870c963a3475a6bace   \n",
       "\n",
       "                                mac                              imsi  \\\n",
       "0  7554648548ef0960bcd5846df31158a1  51e3532c6c7bc2b2e965a82c7cd0e030   \n",
       "1  84d9d352d7a8f1399ff3bf69ae4f923d  7c0ddefb46fa8e83010df6f7ab822b4d   \n",
       "2  620744a255478602e8907eb8b7cccb14  958c048515b88d377c9e652e9b57d44c   \n",
       "3  2f94fc14b3b5ff0594e1e6c04e479220  43f60b5c38e2ad152569e233a5cb88fe   \n",
       "4  fbbe8f9dc741910b6e2b2d739a8254f3  8276231c14b21cf9f8339e53c6482a4a   \n",
       "\n",
       "                         android_id phone_model phone_name networktype  \\\n",
       "0  afc20369ad52cf971becb7b160b42ed6    OPPO R11       OPPO          4G   \n",
       "1  8812c1eb3cbc8e9639fa05dc99306cba    LLD-AL10      HONOR          4G   \n",
       "2                               NaN        M2 E      Meizu        WIFI   \n",
       "3  eef0ca1307bf574408a6f04068c66eb3      PRO 6s      Meizu        WIFI   \n",
       "4  cfb381ccd7104f5728799d0678838378     vivo X7       vivo          4G   \n",
       "\n",
       "  version  ... cellularip networkcountryiso  simcountryiso bluetooth host  \\\n",
       "0   6.2.9  ...        NaN               NaN            NaN       NaN  NaN   \n",
       "1   6.2.9  ...        NaN               NaN            NaN       NaN  NaN   \n",
       "2   6.2.9  ...        NaN               NaN            NaN       NaN  NaN   \n",
       "3   6.2.9  ...        NaN               NaN            NaN       NaN  NaN   \n",
       "4   6.2.8  ...        NaN               NaN            NaN       NaN  NaN   \n",
       "\n",
       "  cpuarchitecture imanufacturer timestamp ethip trueip  \n",
       "0             NaN           NaN       NaN   NaN    NaN  \n",
       "1             NaN           NaN       NaN   NaN    NaN  \n",
       "2             NaN           NaN       NaN   NaN    NaN  \n",
       "3             NaN           NaN       NaN   NaN    NaN  \n",
       "4             NaN           NaN       NaN   NaN    NaN  \n",
       "\n",
       "[5 rows x 72 columns]"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "raw_data.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1 MD5 Hash"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import hashlib\n",
    "\n",
    "def md5_hash(df, feature_columns):\n",
    "    df['concat'] = df[feature_columns].iloc[:, :].astype(str).add('_').sum(axis=1)\n",
    "    \n",
    "    df['md5'] = [hashlib.md5(val.encode(\"UTF8\")).hexdigest() for val in df['concat']]\n",
    "    \n",
    "    return df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "#test_df = md5_hash(raw_data.copy(), [ 'phone_model', 'phone_name'])\n",
    "#test_df['concat']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.1 Information Gain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def entropy(df, label_column):\n",
    "    p_data= df[label_column].value_counts()/len(df) # calculates the probabilities\n",
    "    entropy=stats.entropy(p_data) # input probabilities to get the entropy\n",
    "    return entropy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "DEBUG = False\n",
    "\n",
    "def relative_entropy(df, label_column, feature_column):\n",
    "    if(DEBUG):\n",
    "        print(feature_column)\n",
    "    if label_column == feature_column:\n",
    "        return 0\n",
    "    \n",
    "    df_tmp = df[[label_column, feature_column]]\n",
    "    ## [feature, label, sub_count]\n",
    "    df_feature_label = df_tmp.groupby([feature_column, label_column]).size().reset_index(name='sub_count')\n",
    "    ## [feature, count]\n",
    "    df_feature = df_tmp.groupby(feature_column).size().reset_index(name='count')\n",
    "\n",
    "    ## [feature, label, sub_count, count]\n",
    "    df_group = df_feature_label.merge(df_feature, on = feature_column)\n",
    "    \n",
    "    ## [feature, label, sub_count, count]\n",
    "    ## TODO apply is slow\n",
    "    df_group['group_entropy'] =  df_group.apply(lambda x: math.log(x['count'] / x['sub_count']) * x['sub_count'] / x['count'], axis=1)\n",
    "    ## [feature, group_entropy]\n",
    "    group_entropy = df_group.groupby(feature_column)['group_entropy'].sum().reset_index(name='group_entropy')\n",
    "    \n",
    "    ## [feature, count, ratio]\n",
    "    df_feature['ratio'] = df_feature['count']/ df.shape[0]\n",
    "    relative_env = (group_entropy['group_entropy'] * df_feature['ratio']).sum()\n",
    "    \n",
    "    return relative_env "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "def information_gain(df, label_column, feature_columns):\n",
    "    ent = entropy(df, label_column)\n",
    "    ent_map = [ relative_entropy(df, label_column, column) for column in feature_columns]\n",
    "    ig = ent - ent_map \n",
    "    ig_map = dict(zip(feature_columns, ig))\n",
    "    return ig_map"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*  https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2 Stability"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "def stability_calc(df, label_column, feature_column):\n",
    "    if(DEBUG):\n",
    "        print(feature_column)\n",
    "    if label_column == feature_column:\n",
    "        return 1\n",
    "    \n",
    "    df_tmp = df[[label_column, feature_column]]\n",
    "    \n",
    "     # [label, count], filter label by count\n",
    "    df_label_cnt = df_tmp.groupby(label_column).size().reset_index(name='count')\n",
    "    # at least appear twice, then consider stability\n",
    "    df_label = df_label_cnt[df_label_cnt['count'] > 1]\n",
    "           \n",
    "    # [label, distinct_feature_count]\n",
    "    df_label_feature_cnt = df_tmp.groupby(label_column).agg({feature_column: pd.Series.nunique}).reset_index()\n",
    "    \n",
    "    result = pd.merge(df_label,df_label_feature_cnt,how='inner',on=label_column)\n",
    "    return result[feature_column].sum() /  result.shape[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def stability(df, label_column, feature_columns):\n",
    "    stable_list = [ stability_calc(df, label_column, column) for column in feature_columns]\n",
    "    \n",
    "    stable_map =  dict(zip(feature_columns, stable_list))\n",
    "    #return sorted(stable_map.items(), key=lambda kv: -kv[1])\n",
    "    return stable_map"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3 Evaluation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def evaluation(df, label_column, fp_column):\n",
    "    df_label_fp = df[[label_column, fp_column]].copy()\n",
    "    \n",
    "    label_same = pd.merge(df_label_fp,df_label_fp,how='inner',on=label_column)\n",
    "    fp_same = pd.merge(df_label_fp,df_label_fp,how='inner',on=fp_column)\n",
    "    \n",
    "    sample_cnt = df_label_fp.shape[0]\n",
    "    fp_same_cnt = fp_same.shape[0] - sample_cnt\n",
    "    label_same_cnt = label_same.shape[0] - sample_cnt\n",
    "    truePositiveCnt = fp_same [fp_same.imei_x == fp_same.imei_y].shape[0] - sample_cnt\n",
    "    \n",
    "    recall = truePositiveCnt / label_same_cnt\n",
    "    precision = truePositiveCnt / fp_same_cnt\n",
    "    return {'precision':precision, 'recall':recall}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def fp_evaluation(df, label_column, feature_columns):   \n",
    "    fp_feature_columns = np.setdiff1d(feature_columns, np.array([label_column]))\n",
    "    \n",
    "    md5_hash(df, feature_columns)\n",
    "    ret = evaluation(df, label_column, 'md5')\n",
    "    return ret"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4 特征指标计算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = raw_data.copy()\n",
    "df.fillna('MISSING', inplace=True)\n",
    "\n",
    "label_column = 'imei'\n",
    "feature_columns = df.columns.difference([label_column])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "## waiting time, a cup of coffee, several minutes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "======= information gain =========\n",
      "======= stability =========\n"
     ]
    }
   ],
   "source": [
    "print(\"======= information gain =========\")\n",
    "info_gain = information_gain(df, label_column, feature_columns)\n",
    "\n",
    "print(\"======= stability =========\")\n",
    "stable = stability(df, label_column, feature_columns)\n",
    "\n",
    "df_features = pd.DataFrame([info_gain, stable]).transpose().rename(columns={0:'info_gain', 1:'stable'}).sort_values(by='info_gain',ascending=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_features = df_features.round(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "#df_features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "fp_features = df_features[ (df_features.info_gain > 1) &  (df_features.stable < 1.1 ) ]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>info_gain</th>\n",
       "      <th>stable</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>imsi</th>\n",
       "      <td>9.22</td>\n",
       "      <td>1.01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>simserial</th>\n",
       "      <td>9.21</td>\n",
       "      <td>1.01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mac</th>\n",
       "      <td>8.92</td>\n",
       "      <td>1.03</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>fingerprint</th>\n",
       "      <td>5.97</td>\n",
       "      <td>1.02</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>phone_model</th>\n",
       "      <td>5.36</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>displayrom</th>\n",
       "      <td>5.35</td>\n",
       "      <td>1.01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>product</th>\n",
       "      <td>5.26</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>totalsystem</th>\n",
       "      <td>4.79</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>totalsd</th>\n",
       "      <td>4.79</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>cpuspeed</th>\n",
       "      <td>2.97</td>\n",
       "      <td>1.02</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>lcd</th>\n",
       "      <td>2.65</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>phone_os</th>\n",
       "      <td>2.18</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>phone_name</th>\n",
       "      <td>2.04</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mnc</th>\n",
       "      <td>1.95</td>\n",
       "      <td>1.09</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>hardware</th>\n",
       "      <td>1.64</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>totalmemory</th>\n",
       "      <td>1.11</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             info_gain  stable\n",
       "imsi              9.22    1.01\n",
       "simserial         9.21    1.01\n",
       "mac               8.92    1.03\n",
       "fingerprint       5.97    1.02\n",
       "phone_model       5.36    1.00\n",
       "displayrom        5.35    1.01\n",
       "product           5.26    1.00\n",
       "totalsystem       4.79    1.00\n",
       "totalsd           4.79    1.00\n",
       "cpuspeed          2.97    1.02\n",
       "lcd               2.65    1.00\n",
       "phone_os          2.18    1.00\n",
       "phone_name        2.04    1.00\n",
       "mnc               1.95    1.09\n",
       "hardware          1.64    1.00\n",
       "totalmemory       1.11    1.00"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fp_features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>info_gain</th>\n",
       "      <th>stable</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>mnc</th>\n",
       "      <td>1.95</td>\n",
       "      <td>1.09</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mac</th>\n",
       "      <td>8.92</td>\n",
       "      <td>1.03</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>fingerprint</th>\n",
       "      <td>5.97</td>\n",
       "      <td>1.02</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>cpuspeed</th>\n",
       "      <td>2.97</td>\n",
       "      <td>1.02</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>imsi</th>\n",
       "      <td>9.22</td>\n",
       "      <td>1.01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>simserial</th>\n",
       "      <td>9.21</td>\n",
       "      <td>1.01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>displayrom</th>\n",
       "      <td>5.35</td>\n",
       "      <td>1.01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>phone_model</th>\n",
       "      <td>5.36</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>product</th>\n",
       "      <td>5.26</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>totalsystem</th>\n",
       "      <td>4.79</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>totalsd</th>\n",
       "      <td>4.79</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>lcd</th>\n",
       "      <td>2.65</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>phone_os</th>\n",
       "      <td>2.18</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>phone_name</th>\n",
       "      <td>2.04</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>hardware</th>\n",
       "      <td>1.64</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>totalmemory</th>\n",
       "      <td>1.11</td>\n",
       "      <td>1.00</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             info_gain  stable\n",
       "mnc               1.95    1.09\n",
       "mac               8.92    1.03\n",
       "fingerprint       5.97    1.02\n",
       "cpuspeed          2.97    1.02\n",
       "imsi              9.22    1.01\n",
       "simserial         9.21    1.01\n",
       "displayrom        5.35    1.01\n",
       "phone_model       5.36    1.00\n",
       "product           5.26    1.00\n",
       "totalsystem       4.79    1.00\n",
       "totalsd           4.79    1.00\n",
       "lcd               2.65    1.00\n",
       "phone_os          2.18    1.00\n",
       "phone_name        2.04    1.00\n",
       "hardware          1.64    1.00\n",
       "totalmemory       1.11    1.00"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fp_features.sort_values(by=['stable'], ascending=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(16, 2)"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fp_features.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5  特征筛选"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [],
   "source": [
    "id_columns = ['imsi', 'simserial', 'mac']\n",
    "\n",
    "normal_columns = fp_features.index.difference(id_columns).values.tolist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5.1 ID类特征"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "only imsi\n",
      "{'precision': 0.9986842105263158, 'recall': 0.9908616187989556}\n",
      "only simserial\n",
      "{'precision': 0.6837837837837838, 'recall': 0.9908616187989556}\n",
      "only mac\n",
      "{'precision': 0.005410082823714197, 'recall': 0.9712793733681462}\n"
     ]
    }
   ],
   "source": [
    "for c in id_columns:\n",
    "    print('only ' + c)\n",
    "    ret = fp_evaluation(df, label_column, [c])\n",
    "    print(ret)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5.2 非ID类特征 - 过度关联"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "NO ID Feature \n",
      "{'precision': 0.006752437270257312, 'recall': 0.8825065274151436}\n"
     ]
    }
   ],
   "source": [
    "print('NO ID Feature ')\n",
    "ret = fp_evaluation(df, label_column, normal_columns)\n",
    "print(ret)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5.3 混合 - 过度区分"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'precision': 1.0, 'recall': 0.8472584856396866}\n"
     ]
    }
   ],
   "source": [
    "ret = fp_evaluation(df, label_column, fp_features.index)\n",
    "print(ret)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5.4 forward selection"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [],
   "source": [
    "from IPython.display import display, HTML\n",
    "pd.set_option('max_colwidth', 180)\n",
    "\n",
    "def show_ret(ret_list):\n",
    "    ret_df = pd.DataFrame(ret_list)\n",
    "#     display(ret_df[0:10])\n",
    "    \n",
    "    ax = ret_df.plot(y=['recall'], xticks=ret_df.index, figsize=(10,4), grid=True)\n",
    "    ax.set_xticklabels(ret_df['column'], rotation=90)\n",
    "    \n",
    "    return ret_df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [],
   "source": [
    "candidates = fp_features.index.tolist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [],
   "source": [
    "selected_columns = []\n",
    "left_columns = list(set(candidates) - set(selected_columns)) \n",
    "\n",
    "ret_list = []\n",
    "while( len(left_columns) > 0 ):\n",
    "    max_recall = 0\n",
    "    cur_column = None\n",
    "    cur_ret = None\n",
    "    \n",
    "    if(len(selected_columns) == 0):\n",
    "        ## Don't calc for every single feature. When the information_gain of a feature is low, memory would be explosive for merge in evaluation\n",
    "        cur_column = 'imsi'\n",
    "        cur_ret = fp_evaluation(df, label_column, ['imsi'])\n",
    "    else:\n",
    "        ## Get Best Feature\n",
    "        for c in left_columns:\n",
    "            ret = fp_evaluation(df, label_column, selected_columns + [c])\n",
    "            if(ret['recall'] > max_recall):\n",
    "                max_recall = ret['recall']\n",
    "                cur_column = c\n",
    "                cur_ret = ret\n",
    "\n",
    "    ## Append Best Feature\n",
    "    selected_columns.append(cur_column)\n",
    "    left_columns = list(set(candidates) - set(selected_columns)) \n",
    "    \n",
    "    cur_ret['feature'] = selected_columns.copy()\n",
    "    cur_ret['column'] = cur_column\n",
    "    ret_list.append(cur_ret)\n",
    "    if(DEBUG):\n",
    "        print(cur_column)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>column</th>\n",
       "      <th>feature</th>\n",
       "      <th>precision</th>\n",
       "      <th>recall</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>imsi</td>\n",
       "      <td>[imsi]</td>\n",
       "      <td>0.998684</td>\n",
       "      <td>0.990862</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>phone_name</td>\n",
       "      <td>[imsi, phone_name]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.990862</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>lcd</td>\n",
       "      <td>[imsi, phone_name, lcd]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.990862</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>phone_os</td>\n",
       "      <td>[imsi, phone_name, lcd, phone_os]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.990862</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>totalmemory</td>\n",
       "      <td>[imsi, phone_name, lcd, phone_os, totalmemory]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.990862</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>totalsd</td>\n",
       "      <td>[imsi, phone_name, lcd, phone_os, totalmemory, totalsd]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.990862</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>totalsystem</td>\n",
       "      <td>[imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.990862</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>simserial</td>\n",
       "      <td>[imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.990862</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>phone_model</td>\n",
       "      <td>[imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.990862</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>hardware</td>\n",
       "      <td>[imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model, hardware]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.990862</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>product</td>\n",
       "      <td>[imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model, hardware, product]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.989556</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>displayrom</td>\n",
       "      <td>[imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model, hardware, product, displayrom]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.983029</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>fingerprint</td>\n",
       "      <td>[imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model, hardware, product, displayrom, fingerprint]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.972585</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>cpuspeed</td>\n",
       "      <td>[imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model, hardware, product, displayrom, fingerprint, cpuspeed]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.953003</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>mac</td>\n",
       "      <td>[imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model, hardware, product, displayrom, fingerprint, cpuspeed, mac]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.925587</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>mnc</td>\n",
       "      <td>[imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model, hardware, product, displayrom, fingerprint, cpuspeed, mac, mnc]</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>0.847258</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         column  \\\n",
       "0          imsi   \n",
       "1    phone_name   \n",
       "2           lcd   \n",
       "3      phone_os   \n",
       "4   totalmemory   \n",
       "5       totalsd   \n",
       "6   totalsystem   \n",
       "7     simserial   \n",
       "8   phone_model   \n",
       "9      hardware   \n",
       "10      product   \n",
       "11   displayrom   \n",
       "12  fingerprint   \n",
       "13     cpuspeed   \n",
       "14          mac   \n",
       "15          mnc   \n",
       "\n",
       "                                                                                                                                                         feature  \\\n",
       "0                                                                                                                                                         [imsi]   \n",
       "1                                                                                                                                             [imsi, phone_name]   \n",
       "2                                                                                                                                        [imsi, phone_name, lcd]   \n",
       "3                                                                                                                              [imsi, phone_name, lcd, phone_os]   \n",
       "4                                                                                                                 [imsi, phone_name, lcd, phone_os, totalmemory]   \n",
       "5                                                                                                        [imsi, phone_name, lcd, phone_os, totalmemory, totalsd]   \n",
       "6                                                                                           [imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem]   \n",
       "7                                                                                [imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial]   \n",
       "8                                                                   [imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model]   \n",
       "9                                                         [imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model, hardware]   \n",
       "10                                               [imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model, hardware, product]   \n",
       "11                                   [imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model, hardware, product, displayrom]   \n",
       "12                      [imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model, hardware, product, displayrom, fingerprint]   \n",
       "13            [imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model, hardware, product, displayrom, fingerprint, cpuspeed]   \n",
       "14       [imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model, hardware, product, displayrom, fingerprint, cpuspeed, mac]   \n",
       "15  [imsi, phone_name, lcd, phone_os, totalmemory, totalsd, totalsystem, simserial, phone_model, hardware, product, displayrom, fingerprint, cpuspeed, mac, mnc]   \n",
       "\n",
       "    precision    recall  \n",
       "0    0.998684  0.990862  \n",
       "1    1.000000  0.990862  \n",
       "2    1.000000  0.990862  \n",
       "3    1.000000  0.990862  \n",
       "4    1.000000  0.990862  \n",
       "5    1.000000  0.990862  \n",
       "6    1.000000  0.990862  \n",
       "7    1.000000  0.990862  \n",
       "8    1.000000  0.990862  \n",
       "9    1.000000  0.990862  \n",
       "10   1.000000  0.989556  \n",
       "11   1.000000  0.983029  \n",
       "12   1.000000  0.972585  \n",
       "13   1.000000  0.953003  \n",
       "14   1.000000  0.925587  \n",
       "15   1.000000  0.847258  "
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 720x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_ret(ret_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
